import os
import json
import traceback
import asyncio
import aiohttp
from typing import Dict, Any, List, Optional, Tuple
from sqlalchemy import select
from db import AsyncSessionLocal
from db.models.scan import ScanResult, ScanRecord
from config.settings import settings
from utils.code_parser import FunctionParser
import time
import re
from abc import ABC, abstractmethod
from datetime import datetime, timezone, timedelta
from utils.file_utils import split_c_file
from openai import OpenAI, AsyncOpenAI
from utils.repo import list_source_files
import logging


class AIProvider(ABC):
    """AI服务提供者抽象基类"""

    @abstractmethod
    async def analyze_code(self, prompt: str) -> Dict[str, Any]:
        """分析代码的抽象方法"""
        pass


class OpenAIAIProvider(AIProvider):
    """OpenAI服务提供者实现"""

    def __init__(self, session: aiohttp.ClientSession):
        self.session = session

    async def analyze_code(self, prompt: str) -> Dict[str, Any]:
        """使用OpenAI分析代码"""
        headers = {
            'accept': 'application/json',
            'Content-Type': 'application/json',
        }

        data = {
            'model': settings.AI_MODEL_NAME,
            'messages': [{
                'role': 'user',
                'content': prompt
            }],
            'max_tokens': 2048,
            'presence_penalty': 1.03,
            'frequency_penalty': 1.0,
            'seed': None,
            'temperature': float(settings.AI_TEMPERATURE),
            'top_p': 0.95,
            'stream': True
        }

        max_retries = 3
        timeout = aiohttp.ClientTimeout(total=600)
        retry_delay = 2

        for attempt in range(max_retries):
            try:
                print(f"\n发送请求 (尝试 {attempt + 1}/{max_retries})...")

                async with self.session.post(
                        settings.AI_CHAT_URL,
                        json=data,
                        headers=headers,
                        timeout=timeout
                ) as response:
                    print(f"收到响应，状态码: {response.status}")
                    if response.status == 200:
                        if settings.AI_STREAM_ENABLED.lower() == 'true':
                            analysis_text = await self._process_stream_response(response)
                            return {'analysis': analysis_text}
                        else:
                            result = await response.json()
                            return {'analysis': result.get('text', '')}
                    elif response.status == 401:
                        print("认证过期，重新认证...")
                        continue
                    else:
                        error_text = await response.text()
                        print(f"分析请求失败 (尝试 {attempt + 1}/{max_retries}): {error_text}")
                        if attempt < max_retries - 1:
                            await asyncio.sleep(retry_delay)
                            continue
                        raise Exception(f"分析请求失败: {error_text}")

            except (aiohttp.ClientError, asyncio.TimeoutError) as e:
                print(f"请求出错 (尝试 {attempt + 1}/{max_retries}): {str(e)}")
                if attempt < max_retries - 1:
                    await asyncio.sleep(retry_delay)
                    continue
                raise Exception(f"发送分析请求时出错: {str(e)}")

        raise Exception("达到最大重试次数，请求失败")

    async def _process_stream_response(self, response: aiohttp.ClientResponse) -> str:
        """处理OpenAI的流式响应"""
        print("处理流式响应...")
        print(f"响应状态码: {response.status}")
        print(f"响应头: {response.headers}")

        full_text = ""
        chunk_count = 0
        start_time = time.time()

        try:
            print("开始读取响应内容...")
            async for line in response.content:
                chunk_count += 1
                try:
                    raw_line = line.decode('utf-8').strip()
                    if not raw_line:
                        continue

                    if raw_line == 'data: [DONE]':
                        print("\n收到结束标记 [DONE]")
                        break

                    if not raw_line.startswith('data: '):
                        print(f"警告: 数据块格式不正确: {raw_line[:100]}...")
                        continue

                    data = json.loads(raw_line[6:])
                    if 'choices' in data and len(data['choices']) > 0:
                        delta = data['choices'][0].get('delta', {})
                        if 'content' in delta:
                            chunk_text = delta['content']
                            full_text += chunk_text
                            print(chunk_text, end="")
                    else:
                        print(f"\n警告: 数据块中没有content字段: {data}")
                        continue

                except json.JSONDecodeError as e:
                    print(f"\nJSON解析错误 (数据块 {chunk_count}): {str(e)}")
                    continue
                except UnicodeDecodeError as e:
                    print(f"\n解码错误 (数据块 {chunk_count}): {str(e)}")
                    continue
                except Exception as e:
                    print(f"\n处理数据块 {chunk_count} 时出错: {str(e)}")
                    continue

        except Exception as e:
            print(f"\n处理流式响应时出错: {str(e)}")
            print(f"错误类型: {type(e).__name__}")
            print(f"错误详情: {traceback.format_exc()}")
            raise

        return full_text


class QianWenAIProvider(AIProvider):
    """千问服务提供者实现"""

    def __init__(self, session: aiohttp.ClientSession):
        self.session = session
        self.api_key = settings.ALI_QW_API_KEY
        self.url = settings.ALI_QW_CHAT_URL

    async def analyze_code(self, prompt: str) -> Dict[str, Any]:
        """使用千问分析代码"""
        client = AsyncOpenAI(
            # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key="sk-xxx",
            api_key=self.api_key,
            base_url=self.url,
        )

        print(f"请求URL: {self.url}")

        completion = await client.chat.completions.create(
            model=settings.ALI_QW_MODEL,
            # 此处以qwen-plus为例，可按需更换模型名称。模型列表：https://help.aliyun.com/zh/model-studio/getting-started/models
            messages=[{'role': 'system', 'content': 'You are an experienced C language code audit expert, familiar '
                                                    'with CWE security vulnerability standards, C language memory '
                                                    'management specifications, and performance optimization '
                                                    'guidelines, and skilled at identifying potential quality issues '
                                                    'from code.'},
                      {'role': 'user', 'content': prompt}],
            stream=True,
            stream_options={"include_usage": True}
        )
        analysis_text = await self._process_stream_response(completion)

        return {'analysis': analysis_text}

    async def _process_stream_response(self, response) -> str:
        """处理千问的流式响应"""
        full_response = ""
        try:
            async for chunk in response:
                try:
                    # 使用 model_dump_json() 获取 JSON 字符串
                    data = json.loads(chunk.model_dump_json())
                    
                    # 检查是否有content字段
                    if 'choices' in data and len(data['choices']) > 0:
                        delta = data['choices'][0].get('delta', {})
                        if 'content' in delta and delta['content']:
                            content = delta['content']
                            print(content, end="")
                            full_response += content
                            
                except json.JSONDecodeError as je:
                    print(f"JSON解析错误: {str(je)}")
                    continue
                except Exception as e:
                    print(f"处理数据块时出错: {str(e)}")
                    continue

        except Exception as e:
            print(f"处理流式响应时出错: {str(e)}")
            print(f"错误类型: {type(e).__name__}")
            print(f"错误详情: {traceback.format_exc()}")
            raise

        return full_response


class XunfeiAIProvider(AIProvider):
    """讯飞星火服务提供者实现"""

    def __init__(self, session: aiohttp.ClientSession):
        self.session = session
        self.api_key = settings.XUNFEI_API_KEY
        self.url = settings.XUNFEI_CHAT_URL

    async def analyze_code(self, prompt: str) -> Dict[str, Any]:
        """使用讯飞星火分析代码"""
        headers = {
            'Authorization': self.api_key,
            'content-type': "application/json"
        }

        data = {
            "model": "x1",
            "user": "user_id",
            "messages": [{"role": "user", "content": prompt}],
            "stream": True,
            "tools": [
                {
                    "type": "web_search",
                    "web_search": {
                        "enable": True,
                        "search_mode": "deep"
                    }
                }
            ]
        }

        max_retries = 3
        timeout = aiohttp.ClientTimeout(total=600)
        retry_delay = 2

        for attempt in range(max_retries):
            try:
                print(f"\n发送请求 (尝试 {attempt + 1}/{max_retries})...")
                print(f"请求URL: {self.url}")
                print(f"请求头: {headers}")

                async with self.session.post(
                        self.url,
                        json=data,
                        headers=headers,
                        timeout=timeout
                ) as response:
                    print(f"收到响应，状态码: {response.status}")
                    if response.status == 200:
                        analysis_text = await self._process_stream_response(response)
                        return {'analysis': analysis_text}
                    else:
                        error_text = await response.text()
                        print(f"分析请求失败 (尝试 {attempt + 1}/{max_retries}): {error_text}")
                        if attempt < max_retries - 1:
                            await asyncio.sleep(retry_delay)
                            continue
                        raise Exception(f"分析请求失败: {error_text}")

            except Exception as e:
                print(f"请求出错 (尝试 {attempt + 1}/{max_retries}): {str(e)}")
                if attempt < max_retries - 1:
                    await asyncio.sleep(retry_delay)
                    continue
                raise Exception(f"发送分析请求时出错: {str(e)}")

        raise Exception("达到最大重试次数，请求失败")

    async def _process_stream_response(self, response: aiohttp.ClientResponse) -> str:
        """处理讯飞星火的流式响应"""
        full_response = ""  # 存储返回结果
        is_first_content = True  # 首帧标识

        try:
            async for chunks in response.content:
                if chunks and b'[DONE]' not in chunks:
                    try:
                        # 打印原始数据用于调试
                        raw_data = chunks.decode('utf-8')

                        # 检查数据格式
                        if not raw_data.startswith('data: '):
                            continue

                        # 提取JSON数据
                        data_org = raw_data[6:]  # 跳过 "data: " 前缀

                        # 解析JSON
                        chunk = json.loads(data_org)
                        text = chunk['choices'][0]['delta']

                        # 判断思维链状态并输出
                        if 'reasoning_content' in text and text['reasoning_content']:
                            text["reasoning_content"]

                        # 判断最终结果状态并输出
                        if 'content' in text and text['content']:
                            content = text["content"]
                            if is_first_content:
                                print("\n*******************以上为思维链内容，模型回复内容如下********************\n")
                                is_first_content = False
                            print(content, end="")
                            full_response += content

                    except json.JSONDecodeError as je:
                        print(f"JSON解析错误: {str(je)}")
                        print(f"问题数据: {data_org}")
                        continue
                    except Exception as e:
                        print(f"处理数据块时出错: {str(e)}")
                        continue

        except Exception as e:
            print(f"处理流式响应时出错: {str(e)}")
            print(f"错误类型: {type(e).__name__}")
            print(f"错误详情: {traceback.format_exc()}")
            raise
        print("全部回答" + full_response)
        return full_response

    async def _analyze_code_xunfei(self, prompt: str) -> str:
        """使用讯飞星火API分析代码"""
        try:
            headers = {
                "Authorization": settings.XUNFEI_API_KEY,
                "Content-Type": "application/json"
            }

            data = {
                "model": "x1",
                "user": "user_id",
                "messages": [{"role": "user", "content": prompt}],
                "stream": True,
                "tools": [
                    {
                        "type": "web_search",
                        "web_search": {
                            "enable": True,
                            "search_mode": "deep"
                        }
                    }
                ]
            }

            async with self.session.post(settings.XUNFEI_CHAT_URL, headers=headers, json=data) as response:
                if response.status != 200:
                    error_text = await response.text()
                    print(f"API请求失败: {response.status} - {error_text}")
                    return ""

                return await self._process_stream_response(response)

        except Exception as e:
            print(f"调用讯飞API时出错: {str(e)}")
            print(f"错误类型: {type(e).__name__}")
            print(f"错误堆栈: {traceback.format_exc()}")
            return ""


def _build_prompt(function: Dict[str, Any], context: str) -> str:
    """构建提示词"""
    return f"""
  你是一名经验丰富的 C 语言代码审计专家，熟悉 CWE 安全漏洞标准、C 语言内存管理规范及性能优化准则，擅长从代码中定位潜在质量问题。现有 C 语言项目的源文件及头文件，面向 C 语言开发团队、代码审查人员及项目技术负责人，需对其进行全面扫描，排查内存管理缺陷、安全漏洞、性能瓶颈及编码规范问题。

请严格遵守以下约束：

1. 仅处理 C 语言代码文件（.c 和.h），忽略其他类型文件。
2. 每个问题分析必须关联 CWE 标准编号（如 CWE-415 双重释放）或 C 语言官方规范条款（如 C11 标准 6.7.9 节变量初始化规则）。
3. 禁止输出任何无关解释性语句，仅提供问题相关信息。
4. 不输出思考过程与模拟过程。

请精准定位代码问题，并按照以下格式输出每个问题：

[问题1]
行号: [具体行号]
严重性: [A/B/C/D]
类别: [内存管理/安全漏洞/性能问题/编码规范]
描述: [问题详细描述，包含CWE编号]
代码片段:
[包含错误行的代码片段]
修复建议:
[具体修复建议]

[问题2]
...

若未发现问题，请输出：
[无问题]
            
文件路径: {function['file_path']}
函数名: {function['name']}
行号: {function['start_line']}-{function['end_line']}
代码内容：
```cpp
{function['context']}
```
"""


class AIScanner:
    def __init__(self):
        self.session = None
        self.ai_provider = None

    async def __aenter__(self):
        print("初始化 AIScanner...")
        self.session = aiohttp.ClientSession()
        
        if settings.AI_PROVIDER == "xunfei":
            self.ai_provider = XunfeiAIProvider(self.session)
        elif settings.AI_PROVIDER == "qianWen":
            self.ai_provider = QianWenAIProvider(self.session)
        else:
            self.ai_provider = OpenAIAIProvider(self.session)
        
        print(f"AI提供者已初始化: {settings.AI_PROVIDER}")
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        print("清理 AIScanner 资源...")
        if self.session:
            await self.session.close()
            print("HTTP会话已关闭")
        print("AIScanner 资源清理完成")

    async def analyze_code(self, prompt: str) -> Dict[str, Any]:
        """分析代码"""
        return await self.ai_provider.analyze_code(prompt)


async def run_ai_scan(scan_id: int, repo_path: str, scan_queue: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
    """运行AI扫描"""
    print(f"\n开始AI扫描，仓库路径: {repo_path}")
    print(f"扫描队列大小: {len(scan_queue)}")

    # 创建扫描记录
    scan_record = ScanRecord(
        scan_id=scan_id,
        scan_type="ai",
        status="running",
        start_time=datetime.now(timezone(timedelta(hours=8))),
        end_time=None,
        total_files=len(scan_queue),
        scanned_files=0,
        total_issues=0,
        scan_config={}
    )

    try:
        async with AsyncSessionLocal() as session:
            session.add(scan_record)
            await session.commit()
            print("创建扫描记录成功")
    except Exception as e:
        print(f"创建扫描记录失败: {str(e)}")
        print(f"错误类型: {type(e).__name__}")
        print(f"错误堆栈: {traceback.format_exc()}")
        raise

    results = []
    total_time = 0
    total_segments = len(scan_queue)
    processed_segments = 0
    start_time = time.time()
    concurrent_tasks = 0
    max_concurrent = settings.MAX_CONCURRENT_SCANS

    print(f"\n=== 并发配置 ===")
    print(f"最大并发数: {max_concurrent}")
    print(f"总任务数: {total_segments}")
    print(f"预计并发执行: {'是' if total_segments > 1 else '否'}")

    try:
        async with AIScanner() as scanner:
            # 创建信号量来控制并发数
            semaphore = asyncio.Semaphore(max_concurrent)
            print(f"信号量已创建，最大并发数: {max_concurrent}")

            async def process_segment(segment_info):
                nonlocal processed_segments, concurrent_tasks
                task_id = id(asyncio.current_task())
                
                async with semaphore:
                    concurrent_tasks += 1
                    current_concurrent = concurrent_tasks
                    
                    try:
                        segment_start_time = time.time()
                        print(f"\n[任务{task_id}] 开始处理片段: {segment_info['name']} (文件: {segment_info['path']})")
                        print(f"[任务{task_id}] 当前并发数: {current_concurrent}/{max_concurrent}")

                        # 构建函数信息
                        function_info = {
                            'file_path': segment_info['path'],
                            'name': segment_info['name'],
                            'start_line': segment_info['start_line'],
                            'end_line': segment_info['end_line'],
                            'context': segment_info['content']
                        }

                        # 构建提示词
                        prompt = _build_prompt(function_info, segment_info['content'])

                        # 分析代码
                        print(f"[任务{task_id}] 发送AI分析请求...")
                        response = await scanner.analyze_code(prompt)

                        # 解析响应
                        print(f"[任务{task_id}] 解析AI响应...")
                        issues = _parse_response(response, segment_info['path'], segment_info)

                        # 保存结果
                        if issues:
                            print(f"[任务{task_id}] 保存 {len(issues)} 个问题到数据库...")
                            await _save_scan_results(scan_id, issues)
                            results.extend(issues)

                        segment_time = time.time() - segment_start_time
                        processed_segments += 1
                        
                        # 计算进度
                        progress = (processed_segments / total_segments) * 100
                        print(f"[任务{task_id}] 片段处理完成，耗时: {segment_time:.1f}秒，发现 {len(issues)} 个问题")
                        print(f"\r当前进度: {progress:.1f}% ({processed_segments}/{total_segments})", end="")

                        return segment_time, len(issues)
                    except Exception as e:
                        print(f"[任务{task_id}] 处理代码片段时出错: {str(e)}")
                        print(f"[任务{task_id}] 错误类型: {type(e).__name__}")
                        print(f"[任务{task_id}] 错误堆栈: {traceback.format_exc()}")
                        return 0, 0
                    finally:
                        concurrent_tasks -= 1
                        print(f"[任务{task_id}] 任务结束，当前并发数: {concurrent_tasks}/{max_concurrent}")

            print(f"\n=== 开始并发执行 ===")
            print(f"创建 {total_segments} 个并发任务...")
            
            # 创建并发任务
            tasks = [process_segment(segment) for segment in scan_queue]
            print(f"所有任务已创建，开始并发执行...")

            # 等待所有任务完成
            segment_results = await asyncio.gather(*tasks)
            print(f"\n=== 所有任务执行完成 ===")

            # 更新统计信息
            for segment_time, issues_count in segment_results:
                total_time += segment_time

    except Exception as e:
        print(f"扫描过程出错: {str(e)}")
        print(f"错误类型: {type(e).__name__}")
        print(f"错误堆栈: {traceback.format_exc()}")
        raise
    finally:
        print(f"\n=== 开始清理资源 ===")
        # 更新扫描记录
        try:
            async with AsyncSessionLocal() as session:
                scan_record.status = "completed"
                scan_record.end_time = datetime.now(timezone(timedelta(hours=8)))
                scan_record.scanned_files = total_segments
                await session.commit()
                print("更新扫描记录成功")
        except Exception as e:
            print(f"更新扫描记录失败: {str(e)}")
            print(f"错误类型: {type(e).__name__}")
            print(f"错误堆栈: {traceback.format_exc()}")

    end_time = time.time()
    total_duration = end_time - start_time

    print(f"\n=== 扫描完成统计 ===")
    print(f"总耗时: {total_duration:.1f}秒")
    print(f"处理文件数: {len(scan_queue)}")
    print(f"处理代码片段数: {total_segments}")
    if total_segments > 0:
        print(f"平均速度: {total_time / total_segments:.1f}秒/片段")
        print(f"并发效率: {total_segments / total_duration:.2f}片段/秒")
    print(f"发现总问题数: {len(results)}")
    print(f"程序即将退出...")

    return results


async def _save_scan_results(task_id: int, issues: List[Dict[str, Any]]) -> None:
    """保存扫描结果到数据库"""
    if not issues:
        print("没有发现任何问题，跳过保存")
        return

    print(f"\n开始保存扫描结果到数据库...")
    try:
        async with AsyncSessionLocal() as session:
            # 准备批量插入的数据
            scan_results = []
            valid_issues = 0
            
            for issue in issues:
                try:
                    # 验证必要字段
                    file_path = issue.get('file_path', '')
                    function_name = issue.get('function_name', '')
                    
                    if not file_path or not function_name:
                        print(f"警告: 跳过保存 - 缺少必要字段 - file_path: {file_path}, function_name: {function_name}")
                        continue

                    # 创建 ScanResult 对象
                    scan_result = ScanResult(
                        task_id=task_id,
                        file_path=file_path,
                        function_name=function_name,
                        line_number=issue.get('line_number', '0'),
                        issue_type=issue.get('issue_type', 'other'),
                        severity=issue.get('severity', 'D'),
                        message=issue.get('message', issue.get('description', '未提供描述')),
                        code_snippet=issue.get('code_snippet', ''),
                        suggestion=issue.get('repair_suggestions', '未提供修复建议'),
                        start_line=issue.get('start_line', 0),
                        end_line=issue.get('end_line', 0)
                    )
                    
                    scan_results.append(scan_result)
                    valid_issues += 1
                    print(f"已准备问题: {scan_result.message[:50]}...")

                except Exception as e:
                    print(f"准备单个问题时出错: {str(e)}")
                    print(f"问题数据: {issue}")
                    continue

            # 批量插入
            if scan_results:
                session.add_all(scan_results)
                await session.commit()
                print(f"成功批量保存 {valid_issues} 个问题到数据库")
            else:
                print("没有有效的问题需要保存")

    except Exception as e:
        print(f"保存扫描结果时出错: {str(e)}")
        print(f"错误类型: {type(e).__name__}")
        print(f"错误堆栈: {traceback.format_exc()}")
        raise


def _parse_response(response: Dict[str, Any], file_path: str, segment: Any) -> List[Dict[str, Any]]:
    """解析AI响应"""
    if settings.AI_PROVIDER == "xunfei":
        return _parse_xunfei_response(response, file_path, segment)
    elif settings.AI_PROVIDER == "qianWen":
        return _parse_qianWen_response(response, file_path, segment)
    else:
        return _parse_openai_response(response, file_path, segment)


def _parse_xunfei_response(response: Dict[str, Any], file_path: str, segment: Any) -> List[Dict[str, Any]]:
    """解析讯飞API响应"""
    issues = []
    analysis = response.get('analysis', '')

    if not analysis:
        return issues

    print(f"讯飞AI分析结果: {analysis}")

    # 使用正则表达式匹配问题格式
    # 支持以下格式：
    # 1. 行号格式：
    #    - 单个数字：38
    #    - 带方括号的单个数字：[38]
    #    - 范围：90-91
    #    - 带方括号的范围：[90-91]
    #    - 多行范围：125-127
    #    - 带方括号的多行范围：[125-127]
    # 2. 严重性格式：
    #    - 单个字母：A、B、C、D
    #    - 带方括号：[A]、[B]、[C]、[D]
    # 3. 类别格式：
    #    - 不带方括号：安全漏洞、内存管理、编码规范、性能问题
    #    - 带方括号：[安全漏洞]、[内存管理]、[编码规范]、[性能问题]
    # 4. 代码片段格式：
    #    - 带语言标记：```cpp、```c
    #    - 不带语言标记：```
    #    - 带缩进：```cpp\n    code
    #    - 不带缩进：```cpp\ncode
    #    - 多行代码：```cpp\nline1\nline2
    #    - 空代码块：```cpp\n
    # 5. 修复建议格式：
    #    - 纯文本建议
    #    - 带代码块的建议
    #    - 多行建议
    #    - 带缩进的建议
    issue_pattern = r"\[问题\d+\]\s*\n行号:\s*(?:\[(\d+(?:-\d+)?)\]|(\d+)(?:-\d+)?)\s*\n严重性:\s*(?:\[([A-D])\]|([A-D]))\s*\n类别:\s*(?:\[([^\]]+)\]|([^\n]+))\s*\n描述:\s*([^\n]+)(?:\s*\n代码片段:\s*\n```(?:c|cpp)?\s*\n([\s\S]*?)\s*\n```)?(?:\s*\n修复建议:\s*\n([\s\S]*?)(?:\s*\n```(?:c|cpp)?\s*\n([\s\S]*?)\s*\n```)?)?(?=\s*\n\[问题|$)"

    # 打印原始分析结果以便调试
    print("\n原始分析结果:")
    print(analysis)
    print("\n开始解析问题...")

    matches = re.finditer(issue_pattern, analysis)

    for match in matches:
        try:
            # 处理行号
            line_number = match.group(1) or match.group(2)
            # 处理严重性
            severity = match.group(3) or match.group(4)
            # 处理类别
            category = match.group(5) or match.group(6)
            description = match.group(7)
            code_snippet = match.group(8).strip() if match.group(8) else ""
            repair_suggestions = match.group(9).strip() if match.group(9) else ""
            repair_code = match.group(10).strip() if match.group(10) else ""

            # 打印匹配到的问题信息
            print(f"\n匹配到问题:")
            print(f"行号: {line_number}")
            print(f"严重性: {severity}")
            print(f"类别: {category}")
            print(f"描述: {description}")
            print(f"修复建议: {repair_suggestions}")

            # 处理行号范围
            if '-' in line_number:
                start_line, end_line = map(int, line_number.split('-'))
                line_number = str(start_line)  # 使用起始行号作为主要行号
            else:
                try:
                    line_number = str(int(line_number))
                except ValueError:
                    line_number = '0'  # 如果无法转换为数字，使用0

            # 创建问题对象
            issue = {
                'line_number': line_number,
                'severity': severity,
                'category': category,
                'description': description,
                'code_snippet': code_snippet,
                'repair_suggestions': repair_suggestions + "\n修复代码:\n" + repair_code if repair_code else repair_suggestions,
                'file_path': file_path,
                'function_name': segment.name,
                'start_line': segment.start_line,
                'end_line': segment.end_line,
                'issue_type': category,
                'message': description
            }

            # 验证必要字段
            if not issue['file_path'] or not issue['function_name']:
                print(f"警告: 缺少必要字段 - file_path: {issue['file_path']}, function_name: {issue['function_name']}")
                continue

            issues.append(issue)
            print(f"已找到 {len(issues)} 个问题")

        except Exception as e:
            print(f"解析问题时出错: {str(e)}")
            print(f"问题内容: {match.group(0) if match else 'None'}")
            continue

    return issues


def _parse_qianWen_response(response: Dict[str, Any], file_path: str, segment: Any) -> List[Dict[str, Any]]:
    """解析千问API响应"""
    issues = []
    analysis = response.get('analysis', '')

    if not analysis:
        return issues

    print(f"千问AI分析结果: {analysis}")

    # 打印原始分析结果以便调试
    print("\n原始分析结果:")
    print(analysis)
    print("\n开始解析问题...")

    # 检查是否有问题
    if '[无问题]' in analysis:
        print("AI分析结果：无问题")
        return issues

    # 使用正则表达式匹配所有问题
    problem_pattern = r'\[问题\d+\]\s*\n行号:\s*(\d+(?:-\d+)?)\s*\n严重性:\s*([A-D])\s*\n类别:\s*([^\n]+)\s*\n描述:\s*([^\n]+)(?:\s*\n代码片段:\s*\n```(?:c|cpp)?\s*\n([\s\S]*?)\s*\n```)?(?:\s*\n修复建议:\s*([\s\S]*?))?(?=\s*\n\[问题|$)'
    matches = re.finditer(problem_pattern, analysis)
    print(f"开始匹配问题...")

    for match in matches:
        try:
            # 提取行号
            line_number = match.group(1)
            if not line_number:
                print("未找到行号")
                continue

            # 提取严重性
            severity = match.group(2)
            if not severity:
                print("未找到严重性")
                continue

            # 提取类别
            issue_type = match.group(3)
            if not issue_type:
                print("未找到类别")
                continue

            # 提取描述
            description = match.group(4)
            if not description:
                print("未找到描述")
                continue

            # 提取代码片段
            code_snippet = match.group(5) or ''

            # 提取修复建议
            repair_suggestions = match.group(6) or ''

            # 构建问题对象
            issue = {
                'file_path': file_path,
                'function_name': segment.get('name', 'unknown'),
                'line_number': line_number,
                'issue_type': issue_type,
                'severity': severity,
                'message': description,
                'code_snippet': code_snippet,
                'repair_suggestions': repair_suggestions,
                'start_line': segment.get('start_line', 0),
                'end_line': segment.get('end_line', 0)
            }

            # 验证必要字段
            if not issue['file_path'] or not issue['function_name']:
                print(f"警告: 缺少必要字段 - file_path: {issue['file_path']}, function_name: {issue['function_name']}")
                continue

            issues.append(issue)
            print(f"已找到 {len(issues)} 个问题")
            print(f"问题详情: 行号={line_number}, 严重性={severity}, 类别={issue_type}")

        except Exception as e:
            print(f"解析问题时出错: {str(e)}")
            print(f"问题内容: {match.group(0) if match else 'None'}")
            continue

    print(f"总共解析出 {len(issues)} 个问题")
    return issues


def _parse_openai_response(response: Dict[str, Any], file_path: str, segment: Any) -> List[Dict[str, Any]]:
    """解析OpenAI响应"""
    issues = []
    analysis = response.get('analysis', '')

    if not analysis or '未发现明显问题' in analysis:
        return issues

    print(f"AI分析结果: {analysis}")

    if "[无问题]" not in analysis:
        # 使用正则表达式匹配每个问题，支持多种格式
        issue_pattern = r"\[问题(?:\d+)?\]\n行号:\s*([^\n]+)(?:\n严重性:\s*([A-D]))?\n类别:\s*([^\n]+)\n描述:\s*([^\n]+)(?:\n代码片段:\n([\s\S]*?))?(?=\n修复建议:|$)\n修复建议:\n([\s\S]*?)(?=\n\[问题|$)"
        matches = re.finditer(issue_pattern, analysis)

        # 打印原始分析结果以便调试
        print("\n原始分析结果:")
        print(analysis)
        print("\n开始解析问题...")

        for match in matches:
            try:
                line_number = match.group(1)
                severity = match.group(2) or 'D'  # 如果没有严重性级别，默认为D
                category = match.group(3)
                description = match.group(4)
                code_snippet = match.group(5).strip() if match.group(5) else ""
                repair_suggestions = match.group(6).strip()

                # 处理行号范围
                if '-' in line_number:
                    start_line, end_line = map(int, line_number.split('-'))
                    line_number = str(start_line)  # 使用起始行号作为主要行号
                else:
                    try:
                        line_number = str(int(line_number))
                    except ValueError:
                        line_number = '0'  # 如果无法转换为数字，使用0

                # 打印匹配到的问题信息
                print(f"\n匹配到问题:")
                print(f"行号: {line_number}")
                print(f"严重性: {severity}")
                print(f"类别: {category}")
                print(f"描述: {description}")
                print(f"修复建议: {repair_suggestions}")

                # 创建问题对象，确保所有字段都有默认值
                issue = {
                    'line_number': line_number,
                    'severity': severity or 'D',  # 默认为最低严重性
                    'category': category or '编码规范',  # 默认为编码规范
                    'description': description or '未提供描述',
                    'code_snippet': code_snippet or '',
                    'repair_suggestions': repair_suggestions or '未提供修复建议',
                    'file_path': file_path,
                    'function_name': segment.name,  # 使用对象属性访问
                    'start_line': segment.start_line,  # 使用对象属性访问
                    'end_line': segment.end_line,  # 使用对象属性访问
                    'issue_type': category,
                    'message': description or '未提供描述'  # 使用description作为message
                }

                # 验证必要字段
                if not issue['file_path'] or not issue['function_name']:
                    print(
                        f"警告: 缺少必要字段 - file_path: {issue['file_path']}, function_name: {issue['function_name']}")
                    continue

                issues.append(issue)
                print(f"已找到 {len(issues)} 个问题")
            except Exception as e:
                print(f"解析问题时出错: {str(e)}")
                print(f"问题内容: {match.group(0) if match else 'None'}")
                continue

    return issues
